/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cashmate.struts;

import com.cashmate.hibernate.dao.LoansDAO;
import com.cashmate.hibernate.pojo.Employees;
import com.cashmate.hibernate.pojo.Loans;
import com.cashmate.utilities.Utils;
import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.hibernate.Criteria;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author Dine
 */
public class GridLoans extends ActionSupport {

    private static Logger logger = Logger.getLogger(GridLoans.class);
    private String borrowerid;
    //Your result List
    private List<Loans> gridModel;
    //get how many rows we want to have into the grid - rowNum attribute in the grid
    private Integer rows = 0;
    //Get the requested page. By default grid sets this to 1.
    private Integer page = 0;
    // sorting order - asc or desc
    private String sord;
    // get index row - i.e. user click to sort.
    private String sidx;
    // Your Total Pages
    private Integer total = 0;
    // All Record
    private String filters;
    private Integer records = 0;
    private LoansDAO loandao = (LoansDAO) ServletActionContext.getServletContext().getAttribute("loansDAO");

    @Action(value = "/grid-loans", results = {
        @Result(name = "success", type = "json"),
        @Result(name = "error", location = "../error/messages.jsp")
    })
    @Override
    public String execute() {
        try {
            //max record
            int to = (rows * page);
            //offset record
            int from = to - rows;

            DetachedCriteria criteria = criteria = DetachedCriteria.forClass(Loans.class);
            criteria.createCriteria("areas", "a").setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            criteria.createCriteria("documents", "d").setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            criteria.createCriteria("borrowers", "b").setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            criteria.createCriteria("b.branches", "br").setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
//            criteria.createCriteria("loanapplications").createCriteria("documents", "ld").setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

            //set criteria search restrictions
            if (filters != null && filters.length()>0) {
                JSONObject jsonFilter = (JSONObject) JSONSerializer.toJSON(filters);
                String groupOp = jsonFilter.getString("groupOp");
                JSONArray rules = jsonFilter.getJSONArray("rules");
                if (groupOp.equals("AND")) {
                    criteria.add(doConjunc(rules));
                } else if (groupOp.equals("OR")) {
                    criteria.add(doDisjunc(rules));
                }
//                if (searchField.equals("areacode")) {
//                    criteria.add(Restrictions.like("a.areacode", "%" + searchString + "%"));
//                } else if (searchField.equals("documentno")) {
//                    criteria.add(Restrictions.like("d.documentno", "%" + searchString + "%"));
//                } else if (searchField.equals("borrowercode")) {
//                    String brRegex = Utils.segregate("letters", searchString);
//                    criteria.add(Restrictions.like("b.branchcode", "%" + brRegex + "%"));
//                    String numbers = Utils.segregate("numbers", searchString);
//                    if (numbers != null && numbers.length() > 0) {
//                        int boroRegex = Integer.parseInt(numbers);
//                        criteria.add(Restrictions.like("borrowerid", boroRegex));
//                    }
//                } else if (searchField.equals("loanappdocumentno")) {
//                    criteria.add(Restrictions.like("ld.documentno", "%" + searchString + "%"));
//                } else {
//                    try {
//                        Double val = Double.parseDouble(searchString);
//                        if (searchField.equals("term")) {
//                            criteria.add(Restrictions.eq(searchField, val.intValue()));
//                        } else {
//                            criteria.add(Restrictions.eq(searchField, val));
//                        }
//                    } catch (NumberFormatException nfe) {
//                        criteria.add(Restrictions.like(searchField, "%" + searchString + "%"));
//                    }
//                }
            }
            
            
            
                if (borrowerid!=null && !borrowerid.equals("")) {//if Head Office..
                    //Set grid to show only loanapps in that branch 
                    //This code is equivalent to "from Loanapplications l inner join l.branches b where b.branchcode=:branchcode"
                    //If you look at line 69 - 79 of this file you can see that I joined the foreign keyed tables already...
                    System.out.println("HINDI EMPTY UNG BORROWERID");
                    System.out.println("borroweridpoito:"+borrowerid);
                    criteria.add(Restrictions.eq("b.borrowerid", Integer.parseInt(borrowerid)));
                } else {
                    System.out.println("EMPTY UNG BORROWERID");
                }
            
            

            // count employees
            records = loandao.countByCriteria(criteria);

            // reset count Projection, note: projection when incremented will set entry point for database,
            // so we need to reset it after counting all records.
            criteria.setProjection(null);
            criteria.setResultTransformer(Criteria.ROOT_ENTITY);

            // handle Order By
            if (sidx != null && !sidx.equals("")) {
                if (sidx.equals("borrowercode")) {
                    if (sord.equals("asc")) {
                        criteria.addOrder(Order.asc("br.branchcode")).addOrder(Order.asc("b.borrowerid"));
                    } else {
                        criteria.addOrder(Order.desc("br.branchcode")).addOrder(Order.desc("b.borrowerid"));
                    }
                } else {
                    if (sidx.equals("areacode")) {
                        sidx = "a.areacode";
                    } else if (sidx.equals("documentno")) {
                        sidx = "d.documentno";
                    } else if (sidx.equals("loanappdocumentno")) {
                        sidx = "ld.documentno";
                    }

                    if (sord.equals("asc")) {
                        criteria.addOrder(Order.asc(sidx));
                    } else {
                        criteria.addOrder(Order.desc(sidx));
                    }
                }
            }

            //et to = max rows
            if (to > records) {
                to = records;
            }

            // get all employees by criteria
            gridModel = loandao.findByCriteria(criteria, from, to);

            //total pages
            total = (int) Math.ceil((double) records / (double) rows);
        } catch (Exception e) {
            //catch whichever exception, get the current session info of the employee and log it.
            Employees emps = (Employees) ServletActionContext.getRequest().getSession().getAttribute("employee");
            if (emps != null) {
                logger.fatal("(" + emps.getIdnumber() + "):" + e.getLocalizedMessage(), e);
            } else {
                logger.fatal(e.getLocalizedMessage(), e);
            }
            e.printStackTrace();
            //add action errors this will correspond to <s:actionerror/> in a struts-enabled jsp page.
            addActionError(e.getLocalizedMessage());

            //if error then chain result to messages.jsp, which will display errors/messages.
            return ERROR;
        }
        return SUCCESS;
    }

    public String getJSON() {
        return execute();
    }

    public List<Loans> getGridModel() {
        return gridModel;
    }

    public void setGridModel(List<Loans> gridModel) {
        this.gridModel = gridModel;
    }

    public Integer getPage() {
        return page;
    }

    public void setPage(Integer page) {
        this.page = page;
    }

    public Integer getRecords() {
        return records;
    }

    public void setRecords(Integer records) {
        this.records = records;
    }

    public Integer getRows() {
        return rows;
    }

    public void setRows(Integer rows) {
        this.rows = rows;
    }

    public String getFilters() {
        return filters;
    }

    public void setFilters(String filters) {
        this.filters = filters;
    }

    public String getSidx() {
        return sidx;
    }

    public void setSidx(String sidx) {
        this.sidx = sidx;
    }

    public String getSord() {
        return sord;
    }

    public void setSord(String sord) {
        this.sord = sord;
    }

    public Integer getTotal() {
        return total;
    }

    public void setTotal(Integer total) {
        this.total = total;
    }

    public String getBorrowerid() {
        return borrowerid;
    }

    public void setBorrowerid(String borrowerid) {
        this.borrowerid = borrowerid;
    }
    
    private Disjunction doDisjunc(JSONArray rules) {
        int rulesCount = JSONArray.getDimensions(rules)[0];
        Disjunction dj = Restrictions.disjunction();
        for (int i = 0; i < rulesCount; i++) {
            JSONObject rule = rules.getJSONObject(i);
            String field = rule.getString("field");
            String data = rule.getString("data");
            if (field.equals("areacode")) {
                field = "a.areacode";
            }
            if (field.equals("documentno")) {
                field = "d.documentno";
            }
            if (field.equals("loanappdocumentno")) {
                field = "ld.documentno";
            }
            if (!field.equals("borrowercode")) {
                try {
                    Double val = Double.parseDouble(data);
                    if (field.equals("term")) {
                        dj.add(Restrictions.like(field, val.intValue()));
                    } else {
                        dj.add(Restrictions.like(field, val));
                    }
                } catch (NumberFormatException nfe) {
                    dj.add(Restrictions.like(field, "%" + data + "%"));
                }
            } else {
                String brRegex = Utils.segregate("letters", data);
                dj.add(Restrictions.like("br.branchcode", "%" + brRegex + "%"));
                String numbers = Utils.segregate("numbers", data);
                if (numbers != null && numbers.length() > 0) {
                    int boroRegex = Integer.parseInt(numbers);
                    dj.add(Restrictions.like("b.borrowerid", boroRegex));
                }
            }
        }
        return dj;
    }

    private Conjunction doConjunc(JSONArray rules) {
        int rulesCount = JSONArray.getDimensions(rules)[0];
        Conjunction cj = Restrictions.conjunction();
        for (int i = 0; i < rulesCount; i++) {
            JSONObject rule = rules.getJSONObject(i);
            String field = rule.getString("field");
            String data = rule.getString("data");
            if (field.equals("areacode")) {
                field = "a.areacode";
            }
            if (field.equals("documentno")) {
                field = "d.documentno";
            }
            if (field.equals("loanappdocumentno")) {
                field = "ld.documentno";
            }
            if (!field.equals("borrowercode")) {
                try {
                    Double val = Double.parseDouble(data);
                    if (field.equals("term")) {
                        cj.add(Restrictions.like(field, val.intValue()));
                    } else {
                        cj.add(Restrictions.like(field, val));
                    }
                } catch (NumberFormatException nfe) {
                    cj.add(Restrictions.like(field, "%" + data + "%"));
                }
            } else {
                String brRegex = Utils.segregate("letters", data);
                cj.add(Restrictions.like("br.branchcode", "%" + brRegex + "%"));
                String numbers = Utils.segregate("numbers", data);
                if (numbers != null && numbers.length() > 0) {
                    int boroRegex = Integer.parseInt(numbers);
                    cj.add(Restrictions.like("b.borrowerid", boroRegex));
                }
            }
        }
        return cj;
    }
}
